#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/queue.h>
#include <setjmp.h>
#include <stdarg.h>
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <stdbool.h>

#include <rte_common.h>
#include <rte_log.h>
#include <rte_malloc.h>
#include <rte_memory.h>
#include <rte_memcpy.h>
#include <rte_eal.h>
#include <rte_launch.h>
#include <rte_cycles.h>
#include <rte_prefetch.h>
#include <rte_lcore.h>
#include <rte_per_lcore.h>
#include <rte_branch_prediction.h>
#include <rte_interrupts.h>
#include <rte_random.h>
#include <rte_debug.h>
#include <rte_ether.h>
#include <rte_ethdev.h>
#include <rte_mempool.h>
#include <rte_mbuf.h>
#include <rte_string_fns.h>
#include "sender_forward.h"


extern struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];
extern volatile bool force_quit;

struct lcore_queue_stat lcore_queue_stat[RTE_MAX_LCORE];


static void
fill_ethernet_header(struct rte_ether_hdr *hdr)
{
	struct rte_ether_addr s_addr = {{0xa4, 0xbf, 0x01, 0x6e, 0xcc, 0xef}}; //s2的mac
	struct rte_ether_addr d_addr = {{0xe4, 0x3d, 0x1a, 0xac, 0xc8, 0x04}};//switch eno1np0的mac地址
    //dstaddr=192.168.2.217的mac了A4:BF:01:6E:D3:0F
    //srcaddr=192.168.0.218的mac了 A4:BF:01:6E:A6:7A
	//192.168.1.219的mac地址为：A4:BF:01:6E:CC:EF
    //192.168.63.221 的eno2np0 e4:3d:1a:ac:c8:04
    //192.168.63.221 的eno2np1  e4:3d:1a:ac:c8:05
	hdr->src_addr = s_addr;
	hdr->dst_addr = d_addr;
	hdr->ether_type = rte_cpu_to_be_16(0x0800);
}

static void
fill_ipv4_header(struct rte_ipv4_hdr *hdr)
{
	hdr->version_ihl = (4 << 4) + 5;		  // ipv4, length 5 (*4)
	hdr->type_of_service = 0x03;			  // No Diffserv
	hdr->total_length = rte_cpu_to_be_16(1440); // tcp 20
	hdr->packet_id = rte_cpu_to_be_16(5462);  // set random
	hdr->fragment_offset = rte_cpu_to_be_16(0);
	hdr->time_to_live = 64;
	hdr->next_proto_id = 6; // tcp
	hdr->hdr_checksum = rte_cpu_to_be_16(25295);

	hdr->src_addr = rte_cpu_to_be_32(0xC0A801DB); // 192.168.1.219
	hdr->dst_addr = rte_cpu_to_be_32(0xC0A802D9); // 192.168.2.217
}

static void
fill_tcp_header(struct rte_tcp_hdr *hdr)
{
	hdr->src_port = rte_cpu_to_be_16(0x162E);
	hdr->dst_port = rte_cpu_to_be_16(0x04d2);
	hdr->sent_seq = rte_cpu_to_be_32(0x0);
	hdr->recv_ack = rte_cpu_to_be_32(0);
	hdr->data_off = 0x50;
	hdr->tcp_flags = 0;
	hdr->rx_win = rte_cpu_to_be_16(16);
	hdr->cksum = rte_cpu_to_be_16(0);
	hdr->tcp_urp = rte_cpu_to_be_16(0);
}

static void init_raw_pkt(struct rte_mbuf *m)
{
	//构造数据域
	struct rte_ether_hdr *ether_h;
	struct rte_ipv4_hdr *ipv4_h;

	//以太帧
	ether_h = (struct rte_ether_hdr *)rte_pktmbuf_append(m, sizeof(struct rte_ether_hdr));
	fill_ethernet_header(ether_h);

	// ipv4
	ipv4_h = (struct rte_ipv4_hdr *)rte_pktmbuf_append(m, sizeof(struct rte_ipv4_hdr));
	fill_ipv4_header(ipv4_h);
}


static inline void update_packet_mac(struct rte_ether_hdr *eth)
{
    struct rte_ether_addr d_addr ;
    
    d_addr=eth->dst_addr;
    eth->dst_addr=eth->src_addr;
    eth->src_addr=d_addr;
    
}

static inline void update_packet_ip_addr(struct rte_ipv4_hdr *ip_hdr)
{
    rte_be32_t src_addr;
    src_addr=rte_be_to_cpu_32(ip_hdr->src_addr);
    ip_hdr->src_addr=ip_hdr->dst_addr;
    ip_hdr->dst_addr=rte_cpu_to_le_32(src_addr);
    
}

int forward_mac_ip_updating(struct rte_mbuf *m, struct rte_mbuf *ack_m, unsigned portid)
{
    //源和目的mac地址
    struct rte_ether_addr s_mac;
    struct rte_ether_addr d_mac;

    //源和目的ip地址
    rte_be32_t src_addr;
    rte_be32_t dst_addr;

	struct rte_ether_hdr *eth_hdr;
	struct rte_ipv4_hdr *ipv4_hdr;

    eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); //解析第一个数据包
	ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
    
    s_mac = eth_hdr->src_addr;
    d_mac = eth_hdr->dst_addr;
    src_addr=rte_be_to_cpu_32(ipv4_hdr->src_addr);
    dst_addr=rte_be_to_cpu_32(ipv4_hdr->dst_addr);

    // printf("src_ip:%x\n",src_addr);

    struct rte_ether_hdr *ack_eth_hdr;
	struct rte_ipv4_hdr *ack_ipv4_hdr;

    ack_eth_hdr = rte_pktmbuf_mtod(ack_m, struct rte_ether_hdr *); //解析第一个数据包
	ack_ipv4_hdr = (struct rte_ipv4_hdr *)(ack_eth_hdr + 1);

    //更新源ip和目的ip
    ack_ipv4_hdr->src_addr = rte_cpu_to_be_32(dst_addr); 
    ack_ipv4_hdr->dst_addr = rte_cpu_to_be_32(src_addr); 

    //更新mac地址
    ack_eth_hdr->src_addr = d_mac;
    if(src_addr==0xc0a801db){//如果是s2发来的包，直接填s2的mac地址，就不用走软件交换机
    	struct rte_ether_addr s2_addr = {{0xa4, 0xbf, 0x01, 0x6e, 0xcc, 0xef}}; //s2的mac
	    ack_eth_hdr->dst_addr = s2_addr;
        printf("will send ack to s2\n");
    }else{
        ack_eth_hdr->dst_addr = s_mac;
        printf("will send to s1\n");
    }

	//复制TOS字段
	ack_ipv4_hdr->type_of_service = ipv4_hdr->type_of_service;
}


static void 
l2fwd_simple_forward(struct rte_mbuf *m, struct rte_mbuf *ack_m, unsigned portid,unsigned lcore_id)
{
    int sent;
    //unsigned lcore_id;
    
    forward_mac_ip_updating(m, ack_m, portid);

    sent = rte_eth_tx_burst(portid, 0, &ack_m, 1);

    // printf("pkt length:%d\n",m->pkt_len);
    if (unlikely(sent < 1)) {
        printf("send packet is error\n");
        exit;
	}
    return ;
}

/* main processing loop */
void l2fwd_switch_main_loop(void)
{
	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
    struct rte_mbuf *pkts_sned_burst[SEN_PACKET_BRUST];
	struct rte_mbuf *m;
	int sent;
	unsigned lcore_id;
	uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;
	unsigned i, j, portid, nb_rx;
	struct lcore_queue_conf *qconf;
	struct rte_eth_dev_tx_buffer *buffer;
    struct rte_mempool *pool;

    pool = rte_pktmbuf_pool_create("mempool", 32*1024, 256, 0, 2048 + RTE_PKTMBUF_HEADROOM, rte_socket_id());

	prev_tsc = 0;
	timer_tsc = 0;

	lcore_id = rte_lcore_id();
	qconf = &lcore_queue_conf[lcore_id];

	if (qconf->n_rx_port == 0) {
		RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id);
		return;
	}

	RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id);

	for (i = 0; i < qconf->n_rx_port; i++) {
		portid = qconf->rx_port_list[i];
		RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id,
			portid);
	}
   
    while (!force_quit) {
        
        for (i = 0; i < qconf->n_rx_port; i++) {

			portid = qconf->rx_port_list[i];
            nb_rx = rte_eth_rx_burst(portid, 0,
						 pkts_burst, MAX_PKT_BURST);


			for (j = 0; j < nb_rx; j++) {
                struct rte_mbuf *ack_mbuf;
                ack_mbuf = rte_pktmbuf_alloc(pool);
                init_raw_pkt(ack_mbuf);

                m = pkts_burst[j];
                rte_prefetch0(rte_pktmbuf_mtod(m, void *));
                l2fwd_simple_forward(m, ack_mbuf, portid,lcore_id);
                rte_pktmbuf_free(m);
                rte_pktmbuf_free(ack_mbuf);
			}
		}
    }
}

